package com.sutong.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sutong.client.service.Client;
import com.sutong.common.model.Person;
import com.sutong.common.result.ErrorCode;
import com.sutong.common.service.RemoteInterfaceInfoService;
import com.sutong.platform.constant.CommonConstant;
import com.sutong.platform.exception.BusinessException;
import com.sutong.platform.mapper.InterfaceInfoMapper;
import com.sutong.platform.model.dto.interfaceinfo.InterfaceInfoCallRequest;
import com.sutong.platform.model.dto.interfaceinfo.InterfaceInfoCallResponse;
import com.sutong.platform.model.dto.interfaceinfo.InterfaceInfoQueryRequest;
import com.sutong.platform.model.entity.InterfaceInfo;
import com.sutong.platform.model.entity.User;
import com.sutong.platform.model.enums.InterfaceInfoStatusEnum;
import com.sutong.platform.model.enums.InterfaceParamTypeEnum;
import com.sutong.platform.model.vo.InterfaceInfoDetail;
import com.sutong.platform.model.vo.InterfaceMethodAnalysisVo;
import com.sutong.platform.model.vo.InterfaceTotalVo;
import com.sutong.platform.service.InterfaceInfoService;
import com.sutong.platform.service.InterfaceParamService;
import com.sutong.platform.service.UserInterfaceInfoService;
import com.sutong.platform.utils.SqlUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author sutong
 * @description 接口信息Service实现
 * @createDate 2024-07-09 16:38:50
 */
@Service
@DubboService(interfaceClass = RemoteInterfaceInfoService.class)
public class InterfaceInfoServiceImpl extends ServiceImpl<InterfaceInfoMapper, InterfaceInfo>
        implements InterfaceInfoService, RemoteInterfaceInfoService {

    @Lazy
    @Resource
    private UserInterfaceInfoService userInterfaceInfoService;

    @Resource
    private InterfaceParamService interfaceParamService;

    @Resource
    private RestTemplate restTemplate;

    @Resource
    private InterfaceInfoMapper interfaceInfoMapper;

    @Override
    public QueryWrapper<InterfaceInfo> getQueryWrapper(InterfaceInfoQueryRequest interfaceInfoQueryRequest) {
        if (interfaceInfoQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }
        Long id = interfaceInfoQueryRequest.getId();
        String name = interfaceInfoQueryRequest.getName();
        String description = interfaceInfoQueryRequest.getDescription();
        String url = interfaceInfoQueryRequest.getUrl();
        Integer status = interfaceInfoQueryRequest.getStatus();
        String method = interfaceInfoQueryRequest.getMethod();
        String sortField = interfaceInfoQueryRequest.getSortField();
        String sortOrder = interfaceInfoQueryRequest.getSortOrder();
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjUtil.isNotNull(id), "id", id);
        queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
        queryWrapper.like(StringUtils.isNotBlank(description), "description", description);
        queryWrapper.eq(StringUtils.isNotBlank(url), "url", url);
        queryWrapper.eq(ObjUtil.isNotNull(status), "status", status);
        queryWrapper.eq(StringUtils.isNotBlank(method), "method", method);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField), sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);
        return queryWrapper;
    }

    /**
     * 获取接口详情，包括参数信息
     *
     * @param id
     * @return
     */
    @Override
    public InterfaceInfoDetail getDetailById(Long id) {
        InterfaceInfo interfaceInfo = getById(id);
        if (ObjectUtil.isNull(interfaceInfo)) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        InterfaceInfoDetail interfaceInfoDetail = BeanUtil.copyProperties(interfaceInfo, InterfaceInfoDetail.class);
        CompletableFuture<Void> future1 = CompletableFuture.runAsync(() -> {
            interfaceInfoDetail.setRequestParams(interfaceParamService.listWithTree(id, InterfaceParamTypeEnum.REQUEST_PARAM.getValue()));
            interfaceInfoDetail.setResponseParams(interfaceParamService.listWithTree(id, InterfaceParamTypeEnum.RESPONSE_PARAM.getValue()));
        });
        CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {
            interfaceInfoDetail.setRequestHeaders(interfaceParamService.listWithTree(id, InterfaceParamTypeEnum.REQUEST_HEADER.getValue()));
            interfaceInfoDetail.setResponseHeaders(interfaceParamService.listWithTree(id, InterfaceParamTypeEnum.RESPONSE_HEADER.getValue()));
        });
        CompletableFuture.allOf(future1, future2).join();
        return interfaceInfoDetail;
    }

    /**
     * 调用接口
     *
     * @param callRequest
     * @param loginUser
     * @return
     */
    @Override
    public InterfaceInfoCallResponse interfaceInfoCall(InterfaceInfoCallRequest callRequest, User loginUser) {
        InterfaceInfo interfaceInfo = getById(callRequest.getId());
        if (interfaceInfo == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if (InterfaceInfoStatusEnum.OFFLINE.getValue().equals(interfaceInfo.getStatus())) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "接口已经关闭");
        }

        // TODO 验证请求参数 请求头头是否安装要去传递
        String accessKey = loginUser.getAccessKey();
        String secretKey = loginUser.getSecretKey();
        if (StrUtil.hasEmpty(accessKey, secretKey)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请先申请密钥，再来尝试");
        }
        Client client = new Client(accessKey, secretKey, restTemplate);

        // TODO 调用对应接口
        Person person = JSONUtil.toBean(callRequest.getUserRequestParams(), Person.class);
        InterfaceInfoCallResponse response = new InterfaceInfoCallResponse();
        String res = client.getNameByPostWithJson(person);
        HashMap<String, String> map = new HashMap<>();
        map.put("res", res);
        response.setUserResponseParams(JSONUtil.toJsonStr(map));
        return response;
    }

    @Override
    public Long verifyInterfaceExists(String url, String method) {
        InterfaceInfo interfaceInfo = lambdaQuery().eq(InterfaceInfo::getUrl, url).eq(InterfaceInfo::getMethod, method).one();
        if (ObjectUtil.isNull(interfaceInfo)) {
            return null;
        }
        return interfaceInfo.getId();
    }

    /**
     * 查看接口请求方式占比
     */
    @Override
    public List<InterfaceMethodAnalysisVo> methodAnalysis() {
        List<String> methods = interfaceInfoMapper.selectDisMethod();
        return methods.stream().map(method -> {
            Long count = lambdaQuery().eq(InterfaceInfo::getMethod, method).count();
            InterfaceMethodAnalysisVo interfaceMethodAnalysisVo = new InterfaceMethodAnalysisVo();
            interfaceMethodAnalysisVo.setMethod(method);
            interfaceMethodAnalysisVo.setTotalNum(count);
            return interfaceMethodAnalysisVo;
        }).collect(Collectors.toList());
    }

    /**
     * 首页展示接口统计信息
     */
    @Override
    public InterfaceTotalVo totalAnalysis() {
        Long total = lambdaQuery().count();
        Long totalCall = userInterfaceInfoService.selectTotalNumSum();
        InterfaceInfo interfaceInfo = lambdaQuery()
                .select(InterfaceInfo::getId, InterfaceInfo::getCreateTime)
                .orderBy(true, true, InterfaceInfo::getCreateTime)
                .last("limit 1")
                .one();
        InterfaceTotalVo analysisVo = new InterfaceTotalVo();
        analysisVo.setTotal(total);
        analysisVo.setTotalCall(totalCall);
        analysisVo.setCreateWebsiteTime(ObjectUtil.isNull(interfaceInfo) ? new Date() : interfaceInfo.getCreateTime());
        return analysisVo;
    }
}




